import org.jtikz.TikzGraphics2D;
import java.io.*;
import java.util.ArrayList;
import javax.swing.filechooser.FileFilter;

/**
 * Created by IntelliJ IDEA.
 * User: bo
 * Date: 3/6/12
 * Time: 2:36 PM
 */
public class FileHandler {
    private static FileOutputStream fileOutputStream = null;
    private static ObjectOutputStream objectOutputStream = null;
    private static FileInputStream fileInputStream = null;
    private static ObjectInputStream objectInputStream = null;

    public static void saveQuiverFile(File file, QuiverPanel qp) {
        File writeFile = new File(file.getAbsolutePath() + ".qi");
        QuiverPanelContainer qpc = new QuiverPanelContainer(qp);

        try {
            fileOutputStream = new FileOutputStream(writeFile);
            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(qpc);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                objectOutputStream.flush();
                objectOutputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void saveQuiverSessionFile(File file, ArrayList<QuiverPanel> panels) {
        File writeFile = new File(file.getAbsolutePath() + ".qis");
        ArrayList<QuiverPanelContainer> containers = new ArrayList<QuiverPanelContainer>();
        for (QuiverPanel p : panels) {
            containers.add(new QuiverPanelContainer(p));
        }
        try {
            fileOutputStream = new FileOutputStream(writeFile);
            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(containers);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                objectOutputStream.flush();
                objectOutputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static ArrayList<QuiverPanel> openQuiverSessionFile(File file) {
        ArrayList<QuiverPanel> panels = new ArrayList<QuiverPanel>();
        for (QuiverPanelContainer con : openQuiverPanelContainers(file)) {
            panels.add(con.makeQuiverPanel());
        }
        return panels;
    }

    private static ArrayList<QuiverPanelContainer> openQuiverPanelContainers(File file) {
        ArrayList<QuiverPanelContainer> containers = null;
        try {
            fileInputStream = new FileInputStream(file);
            objectInputStream = new ObjectInputStream(fileInputStream);
            containers = (ArrayList<QuiverPanelContainer>) objectInputStream.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        } finally {
            try {
                objectInputStream.close();
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //TODO - find more specific exception than IOException, e.g corruptstream and invalidcast or sumtn.
        //TODO - display message to user of relevant caught exceptions.
        return containers;
    }

    public static QuiverPanel openQuiverFile(File selectedFile) {
        return openQuiverPanelContainer(selectedFile).makeQuiverPanel();
    }

    private static QuiverPanelContainer openQuiverPanelContainer(File selectedFile) {
        QuiverPanelContainer qpc = null;
        try {
            fileInputStream = new FileInputStream(selectedFile);
            objectInputStream = new ObjectInputStream(fileInputStream);
            qpc = (QuiverPanelContainer) objectInputStream.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        } finally {
            try {
                objectInputStream.close();
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return qpc;
    }

    public static void saveJTikzOutput(File file, QuiverPanel panel) {
        String path = file.getAbsolutePath();
        if (!path.substring(path.length() - 4).equals(".tex")) {
            path += ".tex";
        }
        File writeFile = new File(path);

        try {
            fileOutputStream = new FileOutputStream(writeFile);
            TikzGraphics2D tikz = new TikzGraphics2D(fileOutputStream);
            panel.activeDrawingPanel.paint(tikz);
            tikz.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class QuiverFilter extends FileFilter {
    public boolean accept(File file) {
        return file.isDirectory() || file.getName().toLowerCase().endsWith(".qi");
    }

    public String getDescription() {
        return ".qi Quiver files";
    }
}

class QuiverSessionFilter extends FileFilter {
    public boolean accept(File file) {
        return file.isDirectory() || file.getName().toLowerCase().endsWith(".qis");
    }

    public String getDescription() {
        return ".qis Quiver session files";
    }
}

class QuiverPanelContainer implements Serializable {
    private final Quiver quiver;
    private ArrayList<Representation> representations = null;
    private final Relations relations;
    private final Field field;

    public QuiverPanelContainer(QuiverPanel qp) {
        this.quiver = qp.quiver;
        this.representations = qp.getRepresentations();
        this.relations = qp.getRelations();
        this.field = qp.getField();
    }

    Quiver getQuiver() {
        return quiver;
    }

    ArrayList<Representation> getRepresentations() {
        return representations;
    }

    Relations getRelations() {
        return relations;
    }

    Field getField() {
        return field;
    }

    public QuiverPanel makeQuiverPanel() {
        QuiverPanel qp = new QuiverPanel(getQuiver()); //Might never be null.
        if (getRepresentations() != null) {   //Might be null.
            for (Representation rep : getRepresentations()) {
                qp.addRepresentation(rep);
            }
        }
        qp.setRelations(getRelations());//Might never be null.
        qp.setField(getField());
        return qp;
    }
}

